/**
* 通用 js 方法封装处理（大量参考 Ruoyi）
* Copyright (c) 2024 Youcan
*/

/** 弹窗状态码 */
const MODAL_STATUS = {
    SUCCESS: "success",         //成功
    FAIL: "fail",               //失败
    WARNING: "warning",         //警告
    CANCEL: "cancel",           //取消
};

/** 消息状态码 */
const RESULT_CODE = {
    SUCCESS: 200,               //成功
    CANCEL: 204,                //客户端取消操作
    FAIL: 500,                  //失败
    BAD_REQUEST: 400,           //请求异常
    NO_AUTH: 401,               //没有权限
    REQUEST_FORBIDDEN: 403,     //请求被拒绝
    WARNING: 409,               //业务异常
};

/** 表格类型 */
const TABLE_TYPE = {
    dataTable: 0,               //二维数据表格
    treeTable: 1,               //树形表格视图
}

/** 数据窗口的表格配置 Map */
var tables = {
    instances: new Map(),
    //设置数据表格配置参数
    set: (options) => {
        if (options.id == null || options.id == "" || options.id == undefined || options.id == 'undefined') {
            options.id = 'main-table';
        }
        tables.instances.set(options.id, options);
    },
    //获取数据表格配置参数
    get: (id = 'main-table') => {
        return tables.instances.get(id);
    },
};

/** 引用 Layui 相关组件 */
layui.use(['table', 'treeTable', 'form', 'laydate', 'tree'], () => {});

/** 自定义扩展方法 */
(($ = layui.jquery) => {
    $.extend({
        /**
         * 通用方法封装处理
         */
        base: {
            /**
             * 判断是否为空字符串
             * @param str 字串对象
             */
            isEmpty: (str) => {
                if (str == null) {
                    return true;
                } else if ($.base.trim(str) === '') {
                    return true;
                }
                return false;
            },
            /**
             * 判断是否函数
             * @param obj 对象
             */
            isFunction: (obj) => {
                return typeof obj === "function";
            },
            /**
             * 判断是否移动端
             */
            isMobile: () => {
                return $(window).width() <= 768;
            },
            /**
             * 判断是否为非空字符串
             * @param str 字串对象
             */
            isNotEmpty: (str) => {
                return !$.base.isEmpty(str);
            },
            /**
             * 判断对象是否为空
             * @param obj 字串对象
             */
            isNotNull: (obj) => {
                return !$.base.isNull(obj);
            },
            /**
             * 判断对象是否为空
             * @param obj 对象实例
             */
            isNull: (obj) => {
                if (obj === null || obj === undefined) {
                    return true;
                } else if (obj === "undefined") {
                    return true;
                }
                return false;
            },
            /**
             * 是否为字串
             * @param obj 对象实例
             */
            isString: (obj) => {
                return typeof obj === 'string';
            },
            /**
             * JS睡眠
             * @param obj 对象实例
             */
            sleep: async (time) => {
                let sleepFun = (time) => {
                    return new Promise((resolve) => setTimeout(resolve, time));
                }
                await sleepFun(time);
            },
            /**
             * 空格截取
             * @param str 字串
             */
            trim: (str) => {
                if (str == null) {
                    return "";
                }
                return str.toString().replace(/(^\s*)|(\s*$)|\r|\n/g, "");
            },
        },

        /**
         * 事件处理
         */
        events: {
            handle: (options, event, obj) => {
                if ($.base.isNotNull(options.actions) && $.base.isFunction(options.actions.handleEvent)) {
                    //事件处理器
                    return options.actions.handleEvent(options, event, obj);
                }
                return false;
            },
            callback: (options, event, obj) => {
                if ($.base.isNotNull(options.actions) && $.base.isFunction(options.actions.callbackEvent)) {
                    //回调处理器
                    return options.actions.callbackEvent(options, event, obj);
                }
                return false;
            },
            /** 数据表格事件处理器 */
            handlers: {
                /**
                 * 新增子记录事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                addChildHandler: (options, event, obj) => {
                    let commitUrl = options.actions.addChildUrl;
                    let url = commitUrl + "?parentId=" + obj.data[options.module.idField];
                    $.modal.popupEditor(
                        '新增 [' + options.module.name + '] 子项',
                        url,
                        options.editDialog.width,
                        options.editDialog.height,
                        {
                            buttonId: options.editDialog.submitButtonId,
                            url: commitUrl,
                            method: 'post',
                            callback: (index, layero, that, result) => {
                                let data = $.operate.okData();
                                if (result.code === RESULT_CODE.SUCCESS) {
                                    $.table.refresh(options);
                                    data = $.operate.okData({obj: obj, index, index, layero: layero, that: that, result: result.data});
                                } else {
                                    data = $.operate.failData({obj: obj, index, index, layero: layero, that: that, result: result});
                                }

                                $.events.callback(options, event, data);//处理回调事件
                            },
                        },
                    );
                },
                /**
                 * 新增记录事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                addHandler: (options, event, obj) => {
                    let commitUrl = options.actions.addUrl;
                    let url = options.actions.addUrl;
                    $.modal.popupEditor(
                        '新增 [' + options.module.name + ']',
                        url,
                        options.editDialog.width,
                        options.editDialog.height,
                        {
                            buttonId: options.editDialog.submitButtonId,
                            url: commitUrl,
                            method: 'post',
                            callback: (index, layero, that, result) => {
                                if (result.code === RESULT_CODE.SUCCESS) {
                                    $.table.refresh(options);
                                }

                                let data = $.operate.okData({obj: obj, index: index, layero: layero, that: that, result: result});
                                $.events.callback(options, event, data);//处理回调事件
                            },
                        },
                    );
                },
                /**
                 * 批量删除事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                batchRemoveHandler: (options, event, obj) => {
                    let size = options.module.selectedRows.size;
                    if (size === 0) {
                        $.modal.msgWarning('未选中任何记录');
                        return;
                    }
                    $.modal.confirm('确定要删除选择的 ' + size + ' 条记录？', (okBack) => {
                            let ids = Array.from(options.module.selectedRows.keys()).join();
                            $.operate.save(options.actions.removeUrl, {ids: ids}, 'delete', (result) => {
                                if (result.code === RESULT_CODE.SUCCESS) {
                                    $.table.refresh(options);
                                    $.table.clearSelectedRows(options);
                                }

                                let data = $.operate.okData({obj: obj, result: result});
                                $.events.callback(options, event, data);//处理回调事件
                            });
                        },
                        (cancelBack) => {
                            let data = $.operate.okData({obj: obj, result: cancelBack});
                            $.events.callback(options, event, data);
                        },
                    );
                },
                /**
                 * 单元格编辑事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                cellEditHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 表格复选框事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                checkboxHandler: (options, event, obj) => {
                    if (obj.type === 'all') {
                        let pageData = $.table.getPageData(options.id);
                        pageData.forEach((row) => {
                            $.events.handlers.selectRowHandler(options, 'selectRow', {row: row, checked: obj.checked});
                        });
                    } else {
                        $.events.handlers.selectRowHandler(options, 'selectRow', {row: obj.data, checked: obj.checked});
                    }

                    let data = {
                        count: options.module.selectedRows.size,
                        ids: Array.from(options.module.selectedRows.keys()),
                        rows: Array.from(options.module.selectedRows.values()),
                    };

                    $.events.handlers.selectRowsHandler(options, 'selectRows', data);

                    return data;
                },
                /**
                 * 清空数据事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                clearAllHandler: (options, event, obj) => {
                    $.modal.confirm('确定要清空 [' + options.module.name + '] 的所有数据？', (result) => {
                        $.modal.confirm('珍爱系统，远离清空！！！', (result) => {
                            $.operate.save(options.actions.clearAllUrl, {}, 'delete', (result) => {
                                let data = $.operate.okData();

                                if (result.code === RESULT_CODE.SUCCESS) {
                                    $.table.refresh(options);
                                    $.table.clearSelectedRows(options);

                                    data = $.operate.okData({obj: obj, result: result.data});
                                } else {
                                    data = $.operate.failData({obj: obj, result: result.data});
                                }
                                $.events.callback(options, event, data)//处理回调事件
                            });
                        });
                    });
                },
                /**
                 * 列拖拽宽度后的事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                colResizedHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 列筛选（显示或隐藏）后的事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                colToggledHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 表头自定义元素工具事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                colToolHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 编辑记录行事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                editHandler: (options, event, obj) => {
                    let commitUrl = options.actions.editUrl;
                    let url = commitUrl + "?id=" + obj.data[options.module.idField];

                    $.modal.popupEditor(
                        '编辑 [' + options.module.name + ']',
                        url,
                        options.editDialog.width,
                        options.editDialog.height,
                        {
                            buttonId: options.editDialog.submitButtonId,
                            url: commitUrl,
                            method: 'put',
                            callback: (index, layero, that, result) => {
                                if (result.code === RESULT_CODE.SUCCESS) {
                                    $.table.refresh(options);
                                }
                                result.data = {obj: obj, index, index, layero: layero, that: that};
                                //处理回调事件
                                return $.events.callback(options, event, result);
                            },
                        }
                    );
                },
                /**
                 * 展开树状表格事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                expandTreeHandler: (options, event, obj) => {
                    options.module.tableRef.expandAll(options.id, true);

                    return $.operate.okData({obj: obj});
                },
                /**
                 * 折叠树状表格事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                foldTreeHandler: (options, event, obj) => {
                    options.module.tableRef.expandAll(options.id, false);

                    return $.operate.okData({obj: obj});
                },
                /**
                 * 尾部分页栏事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                pagebarHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 单选框事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                radioHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 删除记录行事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                removeHandler: (options, event, obj) => {
                    $.modal.confirm('确定要删除选择的记录？', (result) => {
                        $.operate.save(options.actions.removeUrl, {ids: obj.data[options.module.idField]}, 'delete', (result) => {
                            if (result.code === RESULT_CODE.SUCCESS) {
                                $.table.refresh(options);
                                $.events.handlers.selectRowHandler(options, event, {row: obj.data, checked: false});
                            }
                            let data = $.operate.okData({obj: obj, result: result});
                            //处理回调事件
                            $.events.callback(options, event, data);
                        });
                    });
                },
                /**
                 * 行单击事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                rowClickHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 行右键菜单事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                rowContextmenuHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
                /**
                 * 表格的行双击事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 */
                rowDoubleHandler: (options, event, obj) => {
                    let url = options.actions.detailUrl + "?id=" + obj.data[options.module.idField];
                    let yes = (index, layero, that) => {
                        $.modal.close(index);

                        let data = $.operate.okData({index: obj, layero: layero, that: that});
                        //处理回调事件
                        $.events.callback(options, event, data);
                    };

                    $.modal.open(
                        {
                            title: '查看 [' + options.module.name + ']',
                            content: url,
                            area: [$.modal.width(options.editDialog.width), $.modal.height(options.editDialog.height)],
                            btn: ['确认'],
                        },
                        yes,
                    );
                },
                /**
                 * 选择记录行事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象:
                 * <pre>
                 *     obj.row 数据行实例
                 *     obj.checked 是否选择
                 * </pre>
                 */
                selectRowHandler: (options, event, obj) => {
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    if (obj.checked) {
                        let id = obj.row[options.module.idField];
                        if (options.module.selectedRows.has(id)) {
                            return;
                        }
                        options.module.selectedRows.set(id, obj.row);
                    } else {
                        let id = obj.row[options.module.idField];
                        if (!options.module.selectedRows.has(id)) {
                            return;
                        }
                        options.module.selectedRows.delete(id);
                    }
                },
                /**
                 * 选择多记录行事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * <pre>
                 *     obj.count 行数
                 *     obj.ids Array 类型 id 数组
                 *     obj.rows Array 类型行数据实例数组
                 * </pre>
                 */
                selectRowsHandler: (options, event, obj) => {
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }
                },
                /**
                 * 表格表头排序切换事件处理器
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                sortHandler: (options, event, obj) => {
                    options.initSort = {"field": obj.field, "type": obj.type};
                    //查询数据表格
                    $.table.search(options.id);

                    return $.operate.okData({obj: obj});
                },
                /**
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                toggleHandler: (options, event, obj) => {
                    //查找查询面板容器
                    if ($.base.isNull(options.queryForm)) {
                        return;
                    }
                    $.queryForm.toggle(options.queryForm.id);

                    return $.operate.okData({obj: obj});
                },
                /**
                 * 单元格工具双击事件
                 * @param options Layui 表格的基础属性，参见：https://layui.dev/docs/2/table/#options
                 * @param event 事件名称字串，如：'edit'
                 * @param obj 事件相关对象
                 * @return 封装好的结果数据，有 code、description、data 字段
                 */
                toolDoubleHandler: (options, event, obj) => {
                    return $.operate.okData({obj: obj});
                },
            },
        },


        /**
         * 弹出层封装处理
         */
        modal: {
            //弹出提示
            alert: (content, type) => {
                layer.alert(content, {
                    icon: $.modal.icon(type),
                    title: "系统提示",
                    btn: ['确认'],
                    btnclass: ['btn btn-primary'],
                });
            },
            //错误提示
            alertError: (content) => {
                $.modal.alert(content, MODAL_STATUS.FAIL);
            },
            //成功提示
            alertSuccess: (content) => {
                $.modal.alert(content, MODAL_STATUS.SUCCESS);
            },
            //警告提示
            alertWarning: (content) => {
                $.modal.alert(content, MODAL_STATUS.WARNING);
            },
            //关闭窗体
            close: (index) => {
                layer.close(index);
            },
            //关闭全部窗体
            closeAll: () => {
                layer.closeAll();
            },
            //关闭遮罩层
            closeLoading: (index) => {
                layer.close(index);
            },
            //确认窗体
            confirm: (content, okBack, cancelBack) => {
                layer.confirm(content, {
                    icon: 3,
                    title: "系统提示",
                    btn: ['确认', '取消']
                }, (index) => {
                    $.modal.close(index);
                    if ($.base.isFunction(okBack)) {
                        okBack(true);
                    }
                }, (index) => {
                    $.modal.close(index);
                    if ($.base.isFunction(cancelBack)) {
                        cancelBack(index);
                    }
                });
            },
            //获取高度
            height: (height = '720px') => {
                if ($.base.isMobile()) {
                    return '100%';
                }
                return height;
            },
            //显示图标
            icon: (type) => {
                let icon = "";
                if (type === MODAL_STATUS.WARNING) {
                    icon = 0;
                } else if (type === MODAL_STATUS.SUCCESS) {
                    icon = 1;
                } else if (type === MODAL_STATUS.FAIL) {
                    icon = 5;
                } else {
                    icon = 3;
                }
                return icon;
            },
            //打开遮罩层
            loading: (message) => {
                return layer.msg(message, {icon: 16, shade: .5});
            },
            //消息提示
            msg: (content, type) => {
                if (type != undefined) {
                    layer.msg(content, {icon: $.modal.icon(type), time: 1000, shift: 5});
                } else {
                    layer.msg(content);
                }
            },
            //失败消息
            msgFail: (content) => {
                $.modal.msg(content, MODAL_STATUS.FAIL);
            },
            //成功消息
            msgSuccess: (content) => {
                $.modal.msg(content, MODAL_STATUS.SUCCESS);
            },
            //警告消息
            msgWarning: (content) => {
                $.modal.msg(content, MODAL_STATUS.WARNING);
            },
            /**
             * 打开模态窗体
             * @param config 弹出的窗体配置，参照：https://layui.dev/docs/2/layer/#options
             * @param yes 点击确定时的回调方法
             * @param cancel 点击取消或关闭按钮时的回调方法
             */
            open: (config, yes, cancel) => {
                //弹窗的基础属性配置项
                let options = Object.assign(
                    {
                        type: 2,
                        area: [$.modal.width(), $.modal.height()],
                        fix: false, //不固定
                        maxmin: $.base.isMobile() ? false : true,
                        btnAlign: $.base.isMobile() ? 'c' : 'r',
                        shade: 0.3,
                        title: 'Youcan',
                        content: 'popup',
                        resize: false,
                        btn: ['确定', '关闭'],
                        //弹层外区域关闭
                        shadeClose: true,
                        yes: yes,
                        cancel: cancel,
                        btn2: cancel,
                    },
                    config,
                );
                layer.open(options); //显示弹窗
            },
            /**
             * 弹出编辑器窗体
             *
             * @param title 标题
             * @param url 页面地址
             * @param width 宽度
             * @param height 高度
             * @param submitConfig 弹窗中表单的配置
             * <pre>
             *     {
             *         submitConfig.url         //提交请求的 URL
             *         submitConfig.method      //提交请求的方法
             *         submitConfig.buttonId    //提交按钮的 ID
             *     }
             * </pre>
             */
            popupEditor: (title, url, width, height, submitConfig) => {
                /** 设置默认值 */
                submitConfig = Object.assign({
                        url: '/',
                        method: 'post',
                        buttonId: 'submit-button',
                    }, submitConfig);

                /** 点击确认时的回调 */
                let yes = (index, layero, that) => {
                    let iframeWindow = window['layui-layer-iframe' + index];                                //获取弹层窗口实例
                    let submit = layero.find('iframe').contents().find("#" + submitConfig.buttonId);        //获取 submit 按钮
                    let submitFilter = $(submit).attr("lay-filter");                                        //通过ID查询 lay-filter 值

                    iframeWindow.layui.form.on('submit(' + submitFilter + ')', (data) => {                  //监听 submit 按钮
                        $.operate.save(submitConfig.url, data.field, submitConfig.method, (result) => {
                            //处理回调事件
                            if ($.base.isFunction(submitConfig.callback)) {
                                submitConfig.callback(index, layero, that, result);
                            }

                            if (result.code === RESULT_CODE.SUCCESS) {
                                $.modal.close(index);
                            }
                        });
                        return false; //一定要返回False来阻止再次提交
                    });

                    submit.trigger('click'); //这里触发弹窗中 submit 按钮的单击事件
                };

                /** 点击关闭时的回调 */
                let cancel = (index, layero, that) => {
                    //处理回调事件
                    if ($.base.isFunction(submitConfig.callback)) {
                        submitConfig.callback(index, layero, that, $.operate.cancelData());
                    }
                    return true;
                };

                //打开 modal 窗体
                $.modal.open(
                    {
                        title: title,
                        content: url,
                        area: [$.modal.width(width), $.modal.height(height)],
                    },
                    yes,
                    cancel,
                );
            },
            //获取宽度
            width: (width = '640px') => {
                if ($.base.isMobile()) {
                    return '100%';
                }
                return width;
            },
        },


        /**
         * 操作封装处理
         */
        operate: {
            cancelData: (data = {}) => {
                return {code: RESULT_CODE.CANCEL, description: MODAL_STATUS.CANCEL, data: data};
            },
            failData: (data = {}) => {
                return {code: RESULT_CODE.FAIL, description: MODAL_STATUS.FAIL, data: data};
            },
            okData: (data = {}) => {
                return {code: RESULT_CODE.SUCCESS, description: MODAL_STATUS.SUCCESS, data: data};
            },
            /**
             * 查询操作，获取后台结果数据
             * @param url 请求url
             * @param data 请求数据
             * @param method 请求方法：get、post等
             * @return 查询结果
             */
            query: (url, data, method, callback) => {
                let loadingIdx = $.modal.loading('操作中。。。');
                let returnData = null;
                let options = {
                    url: url,
                    type: $.base.isEmpty(method) ? "post" : method,
                    data: data,
                    async: false, //同步处理
                    success: (result, textStatus) => {
                        $.modal.closeLoading(loadingIdx);
                        if ($.base.isFunction(callback) && callback(result) === true) {
                            return;
                        }
                        returnData = result;
                        $.operate.successCallback(result);
                    },
                    error: (XMLHttpRequest, textStatus, errorThrown) => {
                        $.modal.closeLoading(loadingIdx);
                        let msg = '服务器调用失败：' + textStatus;
                        returnData = $.operate.failData({code: RESULT_CODE.BAD_REQUEST, description: msg});
                        $.modal.alertError(msg);
                    },
                };

                $.ajax(options);
                return returnData;
            },
            /**
             * 保存|更新操作，刷新表格
             * @param url 请求url
             * @param data 请求数据
             * @param method 请求方法：get、post等
             * @param callback 回调方法，如果为空则使用默认回调；
             */
            save: (url, data, method, callback) => {
                let loadingIdx = $.modal.loading('操作中。。。');
                let options = {
                    url: url,
                    type: $.base.isEmpty(method) ? "post" : method,
                    data: data,
                    success: (result, textStatus) => {
                        $.modal.closeLoading(loadingIdx);
                        if ($.base.isFunction(callback) && callback(result) === true) {
                            return;
                        }
                        $.operate.successCallback(result);
                    },
                    error: (XMLHttpRequest, textStatus, errorThrown) => {
                        $.modal.closeLoading(loadingIdx);
                        $.modal.alertError('服务器调用失败：' + textStatus);
                    },
                };
                $.ajax(options);
            },
            /**
             * 成功回调执行事件（统一处理回调）
             * @param result 结果对象
             */
            successCallback: (result) => {
                if (result.code === RESULT_CODE.SUCCESS) {
                    $.modal.msgSuccess('操作成功');
                } else if (result.code === RESULT_CODE.CANCEL) {
                    $.modal.alertWarning('用户取消操作！');
                } else if (result.code === RESULT_CODE.BAD_REQUEST) {
                    $.modal.alertError('操作失败！');
                } else if (result.code === RESULT_CODE.NO_AUTH) {
                    $.modal.alertError('登录超时，请重新登录！');
                } else if (result.code === RESULT_CODE.REQUEST_FORBIDDEN) {
                    $.modal.alertError('您没有此操作的权限！');
                } else if (result.code === RESULT_CODE.FAIL) {
                    $.modal.alertError(result.description);
                } else {
                    $.modal.alertWarning(result.description)
                }
            },
        },


        /**
         * 查询表单封装处理
         */
        queryForm: {
            /**
             * 获取查询表单数据
             * @param formId 查询表单的ID
             */
            getData: (formId = 'main-form') => {
                let data = {};
                let formFilter = $("#" + formId).attr("lay-filter"); //由ID获取lay-filter属性值
                if ($.base.isNotEmpty(formFilter)) {
                    data = layui.form.val(formFilter); //获取表单数据
                }

                return data;
            },
            init: (options) => {
                if ($.base.isNull(options.queryForm)) {
                    return;
                }

                let formId = '#' + options.queryForm.id;
                if ($.base.isNotEmpty(options.queryForm.searchButtonId)) {
                    $(formId + ' #' + options.queryForm.searchButtonId).click(() => {
                        //触发表单搜索事件
                        if ($.events.handle(options, 'search', {tableId: options.id}) === true) {
                            return;
                        }

                        $.table.search(options);

                        $.events.callback(options, 'search', $.operate.okData());
                    });
                }
                if ($.base.isNotEmpty(options.queryForm.resetButtonId)) {
                    $(formId + ' #' + options.queryForm.resetButtonId).click(() => {
                        //触发表单重置事件
                        if ($.events.handle(options, 'reset', {tableId: options.id}) === true) {
                            return;
                        }

                        $.queryForm.reset(options.queryForm.id);
                        $.table.search(options);

                        $.events.callback(options, 'reset', $.operate.okData());
                    });
                }

                //移动模式下隐藏查询面板
                if ($.base.isMobile()) {
                    $(formId).hide();
                } else {
                    $(formId).show();
                }

                /**
                 * laydate 时间控件绑定
                 * 控件要有"select-time"这个class，ID必须为"startTime"和"endTime"。如果有另一对起止时间控件，则必须重写配置。
                 * 如：
                 * <input id="startTime" class="layui-input select-time" type="text" name="startDate" placeholder="开始日期" autocomplete="off">
                 * <input id="endTime"   class="layui-input select-time" type="text" name="endDate"   placeholder="结束日期" autocomplete="off">
                 */
                if ($(".select-time").length > 0) {
                    let startLayDate;
                    let endLayDate;
                    let laydate = layui.laydate;
                    startLayDate = laydate.render({
                        elem: '#startTime',
                        max: $('#endTime').val(),
                        theme: 'molv',
                        type: $('#startTime').attr("data-type") || 'date',
                        trigger: 'click',
                        done: (value, date) => {
                            //结束时间大于开始时间
                            if (value !== '') {
                                endLayDate.config.min.year = date.year;
                                endLayDate.config.min.month = date.month - 1;
                                endLayDate.config.min.date = date.date;
                            } else {
                                endLayDate.config.min.year = '';
                                endLayDate.config.min.month = '';
                                endLayDate.config.min.date = '';
                            }
                            $('#endTime').trigger('click');
                        }
                    });
                    endLayDate = laydate.render({
                        elem: '#endTime',
                        min: $('#startTime').val(),
                        theme: 'molv',
                        type: $('#endTime').attr("data-type") || 'date',
                        trigger: 'click',
                        done: (value, date) => {
                            //开始时间小于结束时间
                            if (value !== '') {
                                startLayDate.config.max.year = date.year;
                                startLayDate.config.max.month = date.month - 1;
                                startLayDate.config.max.date = date.date;
                            } else {
                                startLayDate.config.max.year = '2099';
                                startLayDate.config.max.month = '12';
                                startLayDate.config.max.date = '31';
                            }
                        }
                    });
                }
            },
            /**
             * 重置查询表单数据
             * @param formId 查询表单的ID
             */
            reset: (formId = 'main-form') => {
                let formFilter = $("#" + formId).attr("lay-filter"); //由ID获取lay-filter属性值

                if ($.base.isNotEmpty(formFilter)) {
                    //重置表单（通过ID获取lay-filter）
                    $('[lay-filter="' + $('#' + formId).attr('lay-filter') + '"]')[0].reset();
                }
            },
            /**
             * 设置查询表单数据
             * @param formId 查询表单的ID
             * @param data 数据对象
             */
            setData: (formId = 'main-form', data) => {
                let formFilter = $("#" + formId).attr("lay-filter"); //由ID获取lay-filter属性值
                if ($.base.isNotEmpty(formFilter)) {
                    layui.form.val(formFilter, data); //设置表单数据
                }
            },
            /**
             * 隐藏|显示 查询表单面板
             * @param formId 查询表单的ID
             */
            toggle: (formId = 'main-form') => {
                let elem = $("#" + formId).parent();
                if ($(elem).css("display") === "none") {
                    $(elem).show("fast");
                } else {
                    $(elem).hide("fast");
                }
            },
        },


        /**
         * Layui表格组件方法封装
         */
        table: {
            /**
             * 构建表格数据行工具条
             * @param actions 业务操作基本参数
             * @param buttons 自定义按钮
             */
            buildRowToolbar: (actions, buttons = '') => {
                let str = '<div class="pear-btn-group">';
                if (actions.addChildFlag) str += '<button class="pear-btn pear-btn-primary pear-btn-xs" round plain lay-event="addChild"><i class="layui-icon layui-icon-add-1"></i>&nbsp;增</button>';
                if (actions.editFlag) str += '<button class="pear-btn pear-btn-warming pear-btn-xs" round plain lay-event="edit"><i class="layui-icon layui-icon-edit"></i>&nbsp;改</button>';
                if (actions.removeFlag) str += '<button class="pear-btn pear-btn-danger pear-btn-xs" round plain lay-event="remove"><i class="layui-icon layui-icon-delete"></i>&nbsp;删</button>';
                str += buttons + '</dev>';
                return str;
            },
            /**
             * 构建表格头部工具条
             * @param actions 业务操作基本参数
             * @param buttons 自定义按钮
             */
            buildTableToolbar: (actions, buttons = '') => {
                let str = '<div class="pear-btn-group">';
                if (actions.addFlag) str += '<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="add"><i class="layui-icon layui-icon-add-1"></i>&nbsp;新增</button>';
                if (actions.batchRemoveFlag) str += '<button class="pear-btn pear-btn-danger pear-btn-sm" plain lay-event="batchRemove"><i class="layui-icon layui-icon-delete"></i>&nbsp;批删</button>';
                if (actions.clearAllFlag) str += '<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="clearAll"><i class="layui-icon layui-icon-close"></i>&nbsp;清空</button>';
                if (actions.exportExcelFlag) str += '<button class="pear-btn pear-btn-warming pear-btn-sm" lay-event="exportExcel"><i class="layui-icon layui-icon-spread-left"></i>&nbsp;导出</button>';
                if (actions.importExcelFlag) str += '<button class="pear-btn pear-btn-warming pear-btn-sm" lay-event="importExcel"><i class="layui-icon layui-icon-shrink-actions"></i>&nbsp;导入</button>';
                if (actions.expandTreeFlag) str += '<button class="pear-btn pear-btn-sm" plain lay-event="expandTree"><i class="layui-icon layui-icon-spread-left"></i>&nbsp;展开</button>';
                if (actions.foldTreeFlag) str += '<button class="pear-btn pear-btn-sm" plain lay-event="foldTree"><i class="layui-icon layui-icon-shrink-right"></i>&nbsp;折叠</button>';
                str += buttons + '</dev>';
                return str;
            },
            /**
             * 清除数据表格选中的行
             * @param tableId 表格 ID
             */
            clearSelectedRows: (tableId = 'main-table') => {
                let options = tableId;
                if ($.base.isString(tableId)) {
                    options = tables.get(tableId);
                }

                if ($.base.isNotNull(options)) {
                    options.module.selectedRows.clear();
                    $.events.handle(options, 'selectRows', {
                        count: 0,
                        ids: Array.from(options.module.selectedRows.keys()),
                        rows: Array.from(options.module.selectedRows.values()),
                    });
                }
            },
            /**
             * 获取当前页所有行表格数据
             * @param tableId 表格 ID
             */
            getPageData: (tableId = 'main-table') => {
                let options = tableId;
                if ($.base.isString(tableId)) {
                    options = tables.get(tableId);
                }

                return options.module.tableRef.getData(tableId);
            },
            /**
             * 初始化数据表格
             * @param options 数据表格的 options
             */
            init: (options) => {
                //初始化 options 参数
                options = $.table.initOptions(options);

                //options 实例入表格 Map
                tables.set(options);

                // 执行表格查询
                $.table.search(options);

                // 初始化数据表格事件
                $.table.initEvent(options);

                //初始化查询表单事件
                $.queryForm.init(options);

                return options;
            },
            /**
             * 初始化二维数据表格事件，内部使用，参考：https://layui.dev/docs/2/table/#table.on
             * @param options Layui 表格的 options
             */
            initEvent: (options) => {
                let table = options.module.tableRef;
                /** 监听表格头部工具栏事件 */
                table.on('toolbar(' + options.id + ')', (obj) => {
                    if ($.events.handle(options, obj.event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }
                    let data = $.operate.okData();
                    //新增记录操作
                    if (obj.event === 'add') {
                        $.events.handlers.addHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }
                    //批量删除操作
                    if (obj.event === 'batchRemove') {
                        $.events.handlers.batchRemoveHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }
                    //清空数据操作
                    if (obj.event === 'clearAll') {
                        $.events.handlers.clearAllHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }
                    //显示/隐藏查询面板操作
                    if (obj.event === 'toggle') {
                        data = $.events.handlers.toggleHandler(options, obj.event, obj);
                    }
                    //展开树状表格操作
                    if (obj.event === 'expandTree') {
                        data = $.events.handlers.expandTreeHandler(options, obj.event, obj);
                    }
                    //折叠树状表格操作
                    if (obj.event === 'foldTree') {
                        data = $.events.handlers.foldTreeHandler(options, obj.event, obj);
                    }

                    //处理回调事件
                    $.events.callback(options, obj.event, data);
                });
                /** 监听表格表头排序切换事件 */
                table.on('sort(' + options.id + ')', (obj) => {
                    let event = 'sort';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.sortHandler(options, 'sort', obj);
                    $.events.callback(options, event, data);//处理回调事件
                });
                /** 监听表格表头自定义元素工具事件 */
                table.on('colTool(' + options.id + ')', (obj) => {
                    let event = obj.event;
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.colToolHandler(options, event, obj);
                    $.events.callback(options, event, data);//处理回调事件
                });
                /** 监听表格列拖拽宽度后的事件 */
                table.on('colResized(' + options.id + ')', (obj) => {
                    let event = 'colResized';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.colResizedHandler(options, event, obj);
                    $.events.callback(options, 'colResized', data);
                });
                /** 监听表格列筛选（显示或隐藏）后的事件 */
                table.on('colToggled(' + options.id + ')', (obj) => {
                    let event = 'colToggled';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.colToggledHandler(options, event, obj);
                    $.events.callback(options, event, data);
                });
                /** 监听表格行单击事件 */
                table.on('row(' + options.id + ')', (obj) => {
                    let event = 'rowClick';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.rowClickHandler(options, event, obj);
                    $.events.callback(options, 'rowClick', data);
                });
                /** 监听表格的行双击事件 */
                table.on('rowDouble(' + options.id + ')', (obj) => {
                    let event = 'rowDouble';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }
                    $.events.handlers.rowDoubleHandler(options, event, obj);
                });
                /** 监听表格行右键菜单事件 */
                table.on('rowContextmenu(' + options.id + ')', (obj) => {
                    let event = 'rowContextmenu';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    $.events.handlers.rowContextmenuHandler(options, event, obj);

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, event, data);
                });
                /** 监听表格单元格编辑事件 */
                table.on('edit(' + options.id + ')', (obj) => {
                    let event = 'cellEdit';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    $.events.handlers.cellEditHandler(options, event, obj);

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, event, data);
                });
                /** 监听表格单元格工具事件「单击触发」 */
                table.on('tool(' + options.id + ')', (obj) => {
                    if ($.events.handle(options, obj.event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }
                    if (obj.event === 'addChild') {
                        $.events.handlers.addChildHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }
                    if (obj.event === 'edit') {
                        $.events.handlers.editHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }
                    if (obj.event === 'remove') {
                        $.events.handlers.removeHandler(options, obj.event, obj);
                        return;//事件 handler 中有弹出层， callback 事件已经被处理
                    }

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, obj.event, data);
                });
                /* 监听表格单元格工具事件「双击触发」 */
                table.on('toolDouble(' + options.id + ')', (obj) => {
                    let event = obj.event;
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    $.events.handlers.toolDoubleHandler(options, event, obj);

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, event, data);
                });
                /** 监听表格复选框事件 */
                table.on('checkbox(' + options.id + ')', (obj) => {
                    let event = 'checkbox';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    let data = $.events.handlers.checkboxHandler(options, event, obj);
                    data.obj = obj;

                    data = $.operate.okData(data);
                    $.events.callback(options, event, data);
                });
                /** 监听表格单选框事件 */
                table.on('radio(' + options.id + ')', (obj) => {
                    let event = 'radio';
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    $.events.handlers.radioHandler(options, event, obj);

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, event, data);
                });
                /** 监听表格尾部分页栏事件 */
                table.on('pagebar(' + options.id + ')', (obj) => {
                    let event = obj.event;
                    if ($.events.handle(options, event, obj) === true) {
                        //如果触发的事件返回true，则中止后续操作
                        return;
                    }

                    $.events.handlers.pagebarHandler(options, event, obj);

                    let data = $.operate.okData({obj, obj});
                    $.events.callback(options, event, data);
                });
            },
            /**
             * 初始化 options 参数
             * @param options 数据表格的 options
             */
            initOptions: (options) => {
                /** 数据表格的参数 */
                options = $.extend({
                    id: 'main-table',                                           //数据表格 id
                    elem: '#main-table',                                        //数据表格元素，与 id 保持名称一致
                    height: $.base.isMobile() ? 'full-20' : 'full-120',         //表格容器高度
                    method: 'post',                                             //请求的方式
                    scrollPos: 'fixed',                                         //重载数据时，保持滚动条位置不变
                    even: true,                                                 //是否开启隔行背景
                    size: $.base.isMobile() ? 'sm' : 'md',                      //设置表格其他尺寸。可选值：sm|md|lg
                    request: {pageName: 'pageNumber', limitName: 'pageSize'},   //定义分页请示参数名
                    cellExpandedMode: 'tips',                                   //单元格默认展开方式
                    defaultToolbar: [                                           //数据表格的头部工具栏右侧图标
                        {title: '查询面板', layEvent: 'toggle', icon: 'layui-icon-search'}, 'filter'
                    ],
                    page: {                                                     //支持传入 laypage 组件的所有参数（某些参数除外，如：jump/elem） - 详见:https://layui.dev/docs/2/laypage/#options
                        layout: $.base.isMobile() ? ['count', 'prev', 'next', 'limit'] : ['limit', 'count', 'prev', 'page', 'next', 'skip'], //自定义分页布局
                        groups: $.base.isMobile() ? 1 : 5,                      //只显示 1 或 5 个连续页码
                        limit: $.base.isMobile() ? 10 : 10,                     //每页显示的条数
                        limits: $.base.isMobile() ? [10, 20, 50] : [10, 20, 50, 100],
                    },
                    pagebar: '#main-pagebar',                                   //分页区域元素
                    title: 'Youcan',                                            //table 的大标题（在文件导出等地方会用到）
                    autoSort: false,                                            //是否由组件自动进行前端排序。若为 false，则需自主排序，即由后端直接返回排序好的数据。
                }, options);

                /** 业务模块参数 */
                let module = $.extend({
                    type: TABLE_TYPE.dataTable,                                 //表格类型（二维数据表格）
                    idField: 'id',                                              //数据表格中 id 字段的字段名
                    name: 'Youcan',                                             //业务模块名称
                    path: '/admin/youcan/',                                     //业务模块操作路径，一定要以'/'结尾
                    tableRef: layui.table,                                      //默认 Layui 表格的实例
                    selectedRows: new Map(),                                    //选中的数据行
                }, options.module);

                /** 编辑对话框参数 */
                let editDialog = $.extend({
                    submitFormId: 'edit-form',                                  //编辑对话框中 form 的 id
                    submitButtonId: 'submit-button',                            //编辑对话框提交按钮的 id
                    width: '720px',                                             //编辑对话框提的宽度
                    height: '640px',                                            //编辑对话框提的高度
                }, options.editDialog);

                /** 查询表单参数 */
                let queryForm = null;
                if ($.base.isNotNull(options.queryForm)) {
                    queryForm = $.extend({
                        id: 'main-form',                                        //查询表单的 id
                        searchButtonId: 'main-form-search',                     //查询表单中搜索按钮的 id
                        resetButtonId: 'main-form-reset',                       //查询表单中重置按钮的 id
                    }, options.queryForm);

                    {   /** 包装before方法，用于填充where查询参数 */
                    let orgBefore = options.before;
                        let warpBefore = (options) => {
                            let where = options.where;
                            if ($.base.isNotNull(options.queryForm)) {
                                where = $.extend(true, where, $.queryForm.getData());
                            }
                            //排序参数带入到where参数中
                            if (options.initSort) {
                                where.sortField = options.initSort.field;
                                where.sortType = options.initSort.type;
                            }
                            options.where = where;

                            if ($.base.isFunction(orgBefore)) {
                                orgBefore(options);
                            }
                        }
                        options.before = warpBefore;
                    }
                }

                /** 业务操作参数 */
                let actions = $.extend({
                    addFlag: false, addUrl: options.module.path + 'add',
                    addChildFlag: false, addChildUrl: options.module.path + 'addChild',
                    removeFlag: false, removeUrl: options.module.path + 'delete',
                    batchRemoveFlag: false, batchRemoveUrl: options.module.path + 'delete',
                    clearCacheFlag: false, clearCacheUrl: options.module.path + 'clearCache',
                    clearAllFlag: false, clearAllUrl: options.module.path + 'clearAll',
                    editFlag: false, editUrl: options.module.path + 'edit',
                    detailFlag: false, detailUrl: options.module.path + 'detail',
                    exportExcelFlag: false, exportExcelUrl: options.module.path + 'exportExcel',
                    importExcelFlag: false, importExcelUrl: options.module.path + 'importExcel',
                    expandTreeFlag: false,                                                          //是否显示表格头部工具栏的"展开"按钮
                    foldTreeFlag: false,                                                            //是否显示表格头部工具栏的"折叠"按钮
                    showDetailOnDoubleClick: false,                                                 //双击行时打开此行记录的详情页面
                    multiPageSelection: true,                                                       //垮页面选择
                }, options.actions);

                options.module = module;            //业务模块参数
                options.editDialog = editDialog;    //查询表单参数
                options.queryForm = queryForm;      //编辑对话框参数
                options.actions = actions;          //业务操作参数

                /** 包装parseData方法，用于根据options.selectedRows选中记录行 */
                {
                    let orgParseData = options.parseData;
                    let warpParseData = (res) => {                      //包装数据解析
                        if ($.base.isNotNull(res.data)) {
                            res.data.forEach(row => {
                                let id = row[options.module.idField];
                                if (options.module.selectedRows.has(id)) {     //如果当前行的 id 在 options.module.selectedRows 中存在
                                    row.LAY_CHECKED = true;             //标记选中
                                }
                            });
                        }
                        if ($.base.isFunction(orgParseData)) {        //触发原parseData方法
                            orgParseData(res);
                        }
                    };
                    options.parseData = warpParseData;
                }

                if (options.module.type === TABLE_TYPE.treeTable) {
                    /** treeTable 组件的特定属性集 */
                    options.tree = $.extend({
                        customName: {                   //定义属性名的集合
                            icon: "customIcon"          //定义图标的属性名称
                        },
                        view: {                     //视图相关的属性集合
                            dblClickExpand: false,      //双击节点时，不展开节点
                            expandAllDefault: true,     //默认展开全部节点
                            showIcon: true,             //显示节点图标
                        },
                        data: {                     //数据相关的属性集合
                            rootPid: '0',               //设置根节点的 pid 属性值
                            cascade: 'none',            //设置复选的级联方式
                        },
                    }, options.tree);

                    options.module.tableRef = layui.treeTable;
                } else {
                    options.module.tableRef = layui.table;
                }

                return options;
            },
            /**
             * 刷新表格数据
             * @param tableId 表格 ID 或 表格的 options属性
             */
            refresh: (tableId = 'main-table') => {
                let options = tableId;
                if ($.base.isString(tableId)) {
                    options = tables.get(tableId);
                }

                options.module.tableRef.reloadData(options.id);

                let data = $.operate.okData({tableId: tableId});
                //处理回调事件
                $.events.callback(options, 'refresh', data);
            },
            /**
             * 搜索表格数据
             * @param tableId （可选）表格 ID，默认为 'main-table'
             * @param data （可选）自定义查询数据
             * @param formId （可选）查询表格
             */
            search: (tableId = 'main-table', data, formId) => {
                let options = tableId;
                if ($.base.isString(tableId)) {
                    options = tables.get(tableId);
                }

                let where = options.where;
                if ($.base.isNotNull(data)) {
                    where = $.extend(true, where, data);
                }
                if ($.base.isNotEmpty(formId)) {
                    if ($.base.isNotNull(data)) {
                        $.queryForm.setData(formId, data);
                    }
                    where = $.extend(true, where, $.queryForm.getData(formId));
                }

                options.where = where;

                options.module.tableRef.render(options);

                $.table.clearSelectedRows(options);

                let result = $.operate.okData({tableId: options.id});
                //处理回调事件
                $.events.callback(options, 'search', result);
            },
        },


        /**
         * Layui树组件方法封装
         */
        tree: {
            /**
             * 获取选中的下级ID数组，内部使用。。。
             */
            getCheckedChildren: (data, checkedTreeIds) => {
                for(let i = 0; i < data.length; i++){
                    checkedTreeIds.push(data[i].id);
                    if (data[i].children && data[i].children.length > 0) {
                        $.tree.getCheckedChildren(data[i].children, checkedTreeIds);
                    }
                }
            },
            /**
             * 获取树中已选择的节点ID
             * @param id 树控件HTML元素ID
             * @returns 节点ID数组，如：[1,2,3]
             */
            getCheckedIds : (id) => {
                let checkedTreeIds = [];
                $.tree.getCheckedChildren(layui.tree.getChecked(id), checkedTreeIds);
                return checkedTreeIds;
            },
            /**
             * 设置树中已选中的节点
             * @param id
             * @param data
             * @param checkedIds
             */
            selectChecked: (id, data, checkedIds) => {
                let hasId = (ids, id) => {
                    for (let i = 0; i < ids.length; i++) {
                        if (ids[i] == id) {
                            return true;
                        }
                    }

                    return false;
                };

                if (checkedIds.length == 0) return;
                for (let i = 0; i < data.length; i++) { //遍历所有
                    if (data[i].children && data[i].children.length > 0) {
                        $.tree.selectChecked(id, data[i].children, checkedIds); //支节点则递归
                    } else if (hasId(checkedIds, data[i].id)) {
                        layui.tree.setChecked(id, data[i].id); //叶节点则选中
                    }
                }
            },
        },

    });
})(layui.jquery);
